package com.akkainaction.helloactor.circuitbreaker.actor;

import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.pattern.CircuitBreaker;
import com.akkainaction.helloactor.circuitbreaker.util.DateUtils;
import scala.concurrent.duration.Duration;

import java.util.concurrent.TimeUnit;

public class WorkerActor extends UntypedActor {

    LoggingAdapter log = Logging.getLogger(this.getContext().system(), this);

    private CircuitBreaker breaker;

    @Override
    public void preStart() throws Exception {
        log.info("WorkerActor preStart");
        //maxFailures=5、callTimeout=2秒、resetTimeout=1分钟
        //当向WorkerActor转发“sync”为开头的字符串后，会进入同步处理的代码里，在这里，我们等待了3秒钟，以便能触发超时并计数一次，当计数达到5次后，CircuitBreaker会处于Open状态，
        //此时回调函数onOpen会被调用，而后续的处理会直接失败（calls are failing fast）。
        //1分钟（resetTimeout）之后，circuit breaker进入Half-Open状态，此时回调函数onHalfOpen会被调用。
        //继续发送消息后，假如被成功处理，那么circuit breaker会进入Closed状态，并调用onClose函数，假如失败，则进入Open状态。
        this.breaker = new CircuitBreaker(getContext().dispatcher(), getContext().system().scheduler(), 5, Duration.create(2, TimeUnit.SECONDS), Duration.create(1, TimeUnit.MINUTES))
                .onOpen(() -> System.out.println(DateUtils.getCurrentDateStr() + "--->Actor CircuitBreaker 开启"))
                .onHalfOpen(() -> System.out.println(DateUtils.getCurrentDateStr() + "--->Actor CircuitBreaker 半开启"));
    }

    @Override
    public void postStop() throws Exception {
        log.info("WorkerActor postStop");
    }

    @Override
    public void onReceive(Object message) throws Exception {
        log.info("WorkerActor收到消息：" + message);
        if (message instanceof String) {
            String msg = (String) message;
            if (msg.startsWith("sync")) {
                getSender().tell(breaker.callWithSyncCircuitBreaker(() -> {
                    System.out.println("message:" + msg);
                    Thread.sleep(3000);
                    return msg;
                }), getSelf());
            }
        }
    }
}
